package internal

// Fields type defines the dynamic field collection of the log.
// After Fields are created, their stored keys will not change.
type Fields map[string]interface{}

// Clone returns a cloned Fields.
// If n is given, the returned fields will be pre-expanded with equal capacity.
func (fs Fields) Clone(n int) Fields {
	if len(fs) == 0 {
		return make(Fields, n)
	}
	r := make(Fields, len(fs)+n)
	for k, v := range fs {
		r[k] = v
	}
	return r
}

// With returns a cloned Fields and adds the given data to it.
func (fs Fields) With(src map[string]interface{}) Fields {
	if len(src) == 0 {
		return fs.Clone(0)
	}
	r := fs.Clone(len(src))
	for k, v := range src {
		r[k] = v
	}
	return r
}

// StandardiseFieldsForJSONEncoder standardizes the given log fields.
func StandardiseFieldsForJSONEncoder(src map[string]interface{}) map[string]interface{} {
	dst := make(map[string]interface{}, len(src))
	for k, v := range src {
		switch o := v.(type) {
		case error:
			// The json.Marshal will convert some errors into "{}", we need to call
			// the error.Error() method before JSON encoding.
			dst[k] = o.Error()
		default:
			dst[k] = v
		}
	}
	return dst
}
